#include "ColorWidget.h"
#include <QColorDialog>
#include "ui_ColorWidget.h"

#include "Object.h"
#include "Material.h"


namespace
{
    const float fac = 1.f/255.f;
}


ColorWidget::ColorWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ColorWidget)
{
    ui->setupUi(this);
    ui->shininessWidget->setVisible(false);
    setEnabled(false);

    material = NULL;
}

ColorWidget::~ColorWidget()
{
    delete ui;
}

void ColorWidget::setObject(Object *obj)
{
    if(obj == NULL)
    {
        setEnabled(false);
        material = NULL;
        return;
    }
    setEnabled(true);

    material = obj->getMaterial();

    ui->rSpin->blockSignals(true);
    ui->gSpin->blockSignals(true);
    ui->bSpin->blockSignals(true);

    Vector3i diffuse = (Vector3i)(material->getDiffuse() * 255);
    ui->rSlider->setValue(diffuse.x);
    ui->gSlider->setValue(diffuse.y);
    ui->bSlider->setValue(diffuse.z);
    ui->diffuseFrame->setStyleSheet(QString("background-color: rgb( %1, %2, %3);").arg(diffuse.x).arg(diffuse.y).arg(diffuse.z));

    Vector3i specular = (Vector3i)(material->getSpecular() * 255);
    ui->specularFrame->setStyleSheet(QString("background-color: rgb( %1, %2, %3);").arg(specular.x).arg(specular.y).arg(specular.z));

    int s = material->getShininess();
    ui->shininessFrame->setStyleSheet(QString("background-color: rgb( %1, %2, %3);").arg(s).arg(s).arg(s));

    ui->rSpin->blockSignals(false);
    ui->gSpin->blockSignals(false);
    ui->bSpin->blockSignals(false);

    ui->comboBox->setCurrentIndex(0);
}

void ColorWidget::onColorChanged()
{
    int r = ui->rSpin->value();
    int g = ui->gSpin->value();
    int b = ui->bSpin->value();

    switch(ui->comboBox->currentIndex())
    {
    case 0: //Diffuse
        if(material)
            material->setDiffuse(r*fac, g*fac, b*fac);
        ui->diffuseFrame->setStyleSheet(QString("background-color: rgb( %1, %2, %3);").arg(r).arg(g).arg(b));
        break;
    case 1: //Specular
        if(material)
            material->setSpecular(r*fac, g*fac, b*fac);
        ui->specularFrame->setStyleSheet(QString("background-color: rgb( %1, %2, %3);").arg(r).arg(g).arg(b));
        break;
    }

    emit updated();
}

void ColorWidget::setColor(int r, int g, int b)
{
    ui->rSpin->setValue(r);
    ui->gSpin->setValue(g);
    ui->bSpin->setValue(b);
}

void ColorWidget::onDiffuseButton()
{
    ui->comboBox->setCurrentIndex(0);

    int r = ui->rSpin->value();
    int g = ui->gSpin->value();
    int b = ui->bSpin->value();

    QColorDialog dialog(QColor::fromRgb(r, g, b));

    if(dialog.exec() == QDialog::Accepted)
    {
        QColor color = dialog.currentColor();
        setColor(color.red(), color.green(), color.blue());
    }
}

void ColorWidget::onSpecularButton()
{
    ui->comboBox->setCurrentIndex(1);

    int r = ui->rSpin->value();
    int g = ui->gSpin->value();
    int b = ui->bSpin->value();

    QColorDialog dialog(QColor::fromRgb(r, g, b));

    if(dialog.exec() == QDialog::Accepted)
    {
        QColor color = dialog.currentColor();
        setColor(color.red(), color.green(), color.blue());
    }
}

void ColorWidget::onShininessButton()
{
    ui->comboBox->setCurrentIndex(2);
}

void ColorWidget::onShininessChanged()
{
    if(material)
        material->setShininess(ui->shininessBox->value());

    int v = (ui->shininessBox->value() / (float)ui->shininessBox->maximum()) * 255.0;
    ui->shininessFrame->setStyleSheet(QString("background-color: rgb( %1, %2, %3);").arg(v).arg(v).arg(v));
    emit updated();
}

void ColorWidget::onIndexChanged(int i)
{
    ui->rSpin->blockSignals(true);
    ui->gSpin->blockSignals(true);
    ui->bSpin->blockSignals(true);
    ui->shininessBox->blockSignals(true);

    switch(i)
    {
    case 0: //Diffuse
        ui->rgbWidget->setVisible(true);
        ui->shininessWidget->setVisible(false);
        if(material)
        {
            Vector3i diffuse = (Vector3i)(material->getDiffuse() * 255);
            ui->rSlider->setValue(diffuse.x);
            ui->gSlider->setValue(diffuse.y);
            ui->bSlider->setValue(diffuse.z);
        }
        break;
    case 1: //Specular
        ui->rgbWidget->setVisible(true);
        ui->shininessWidget->setVisible(false);
        if(material)
        {
            Vector3i specular = (Vector3i)(material->getSpecular() * 255);
            ui->rSlider->setValue(specular.x);
            ui->gSlider->setValue(specular.y);
            ui->bSlider->setValue(specular.z);
        }
        break;
    case 2: //Shininess
        ui->rgbWidget->setVisible(false);
        ui->shininessWidget->setVisible(true);
        if(material)
            ui->shininessSlider->setValue(material->getShininess());
        break;
    }

    ui->rSpin->blockSignals(false);
    ui->gSpin->blockSignals(false);
    ui->bSpin->blockSignals(false);
    ui->shininessBox->blockSignals(false);
}
